package org.tigr.htc.server;

/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

import java.io.File;
import java.lang.reflect.Constructor;

import org.apache.log4j.Logger;
import org.tigr.htc.cmd.Command;
import org.tigr.htc.cmd.CommandSet;
import org.tigr.htc.cmd.CommandType;
import org.tigr.htc.cmd.ICommand;
import org.tigr.htc.common.HTCConfig;
import org.tigr.htc.server.condor.CondorRunner;
import org.tigr.htc.server.mw.Runner;
import org.tigr.htc.server.sge.SgeRunner;

public class RunnerFactory {
	// static class no public constructor
	private RunnerFactory() {}

	private static Logger logger = Logger.getLogger(RunnerFactory.class);

	/**
	 * The method <code>newRunner</code> creates a new runner class to launch the command
	 * on the grid.
	 * 
	 * @param cmd <code>ICommand</code> class that is to be executed on the grid
	 * @param cwd <code>File</code> class representing the current working directory
	 * 
	 * @return <code>IRunner</code> that can launch the job on the grid
	 * @throws Exception
	 */
	public static IRunner newRunner(ICommand cmd, File cwd)
			throws Exception {
		logger.debug("Creating runner for Command: " + cmd.getID());

		//
		// command type 'htc' is the default type 
		// which needs to be looked up in the server config file
		// 
		if (cmd.getType().equals(CommandType.HTC)
				|| cmd.getType().equals(CommandType.INTERNAL)) {
			String className = HTCConfig.getProperty("grid.runner");
			logger.debug("Read grid runner class name: " + className);

			// Prepare the parameter types array to get a particular constructor 
			// object
			Class[] paramTypes = { Command.class, File.class };

			// Load class with the same name as the obtained class name and get the
			// constructor
			Class runnerClass = Class.forName(className);
			logger.debug("Obtained class: " + runnerClass.getName());

			Constructor constructor = runnerClass.getConstructor(paramTypes);
			logger.debug("Obtained constructor: " + constructor);

			// Create a new instance with appropriate parameters.
			Object[] params = { (Command) cmd, cwd };

			IRunner runner = (IRunner) constructor.newInstance(params);
			return runner;
		} else if (cmd.getType().equals(CommandType.SSH)) {
			return (IRunner) new SSHRunner((Command) cmd, cwd);
		} else if (cmd.getType().equals(CommandType.SGE)) {
			// If the command type is SGE then create the SGERunner class
			return (IRunner) new SgeRunner((Command) cmd, cwd);
		} else if (cmd.getType().equals(CommandType.CONDOR)) {
			return (IRunner) new CondorRunner((Command) cmd, cwd);
		} else if (cmd.getType().equals(CommandType.COMPOSITE)) {
			return (IRunner) new CompositeRunner((CommandSet) cmd, cwd);
		} else if (cmd.getType().equals(CommandType.MW)) {
			return (IRunner) new Runner((Command) cmd, cwd);
		} else {
			throw new Exception("unknown request/command type "
					+ cmd.getType());
		}
	}
}
